#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int N=1e3;
int h[N],to[N],ne[N],idx;
int depth[N];
int maxn;
struct cmp{
	
	bool operator()(const pair<int,int>& p1,const pair<int,int>& p2){
		return p1.second>p2.second;
	}
};
void add(int x,int y){
	
	ne[idx]=h[x];
	to[idx]=y;
	h[x]=idx++;
}
void get_depth(int u){
	
	priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> q;
	q.push({u,0});
	while(q.size()){
		int root=q.top().first;
		q.pop();
		for(int i=h[root];~i;i=ne[i]){
			int j=to[i];
			if(depth[j]<depth[root]+1){
				depth[j]=depth[root]+1;
				maxn=max(maxn,depth[j]);
				q.push({j,depth[j]});
			}
		}
	}
}
vector<vector<char>> get_Union(){
	
	vector<vector<char>> vecRet;
	for(int d=0;d<=maxn;++d){
		vector<char> vecTmp;
		for(int i=0;i<10;++i){
			if(depth[i]==d){
				vecTmp.push_back(i+'a');
			}
		}
		if(vecTmp.size()){
			vecRet.push_back(vecTmp);
		}
		
	}
	return vecRet;
}
int main(){
	
	vector<string> vecStr;
	memset(h,-1,sizeof(h));
	memset(depth,-0x3f3f3f3f,sizeof(depth));
	add(100,'a'-'a');
	add(100,'c'-'a');
	add('a'-'a','d'-'a');
	add('a'-'a','e'-'a');
	add('a'-'a','f'-'a');
	add('b'-'a','d'-'a');
	add('b'-'a','e'-'a');
	add('b'-'a','f'-'a');	
	add('c'-'a','d'-'a');
	add('c'-'a','e'-'a');
	add('c'-'a','f'-'a');
	add('a'-'a','b'-'a');
	depth[100]=0;
	get_depth(100);
	vector<vector<char>> vecRet=get_Union();
	for(int i=0;i<vecRet.size();++i){
		cout<<"{";
		for(int j=0;j<vecRet[i].size();++j){
			cout<<vecRet[i][j]<<' ';
		}
		cout<<"}";
	}
	
	return 0;
}
